import 'dart:convert';
import 'dart:io';
import 'package:base_plugin/base_plugin.dart' hide Lock;
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/entities/chat_room_message_entity.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:synchronized/synchronized.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

import 'socket_request.dart';

class MyHttpOverrides extends HttpOverrides {
  @override
  HttpClient createHttpClient(SecurityContext context) {
    return super.createHttpClient(context)
      ..badCertificateCallback =
          (X509Certificate cert, String host, int port) => true;
  }
}

class WebSocketProvide with ChangeNotifier {
  var connecting = false; //webSocket连接状态
  static WebSocketChannel channel;

  static WebSocketProvide _singleton;
  static Lock _lock = Lock();

  static Future<WebSocketProvide> getInstance() async {
    if (_singleton == null) {
      await _lock.synchronized(() async {
        if (_singleton == null) {
          // keep local instance till it is fully initialized.
          // 保持本地实例«直到完全初始化。
          var singleton = WebSocketProvide._();
          await singleton._init();
          _singleton = singleton;
        }
      });
    }
    return _singleton;
  }

  WebSocketProvide._();

  _init() {
    isClose = false;
    Uri uri = Uri.parse(Config.webSocketUrl +
        ':6001/app/acesoft?protocol=7&client=js&version=7.0.3&flash=false');
    channel = WebSocketChannel.connect(uri);
    //监听到服务器返回消息
    channel.stream.listen((data) => _listenMessage(data),
        onError: onError, onDone: onDone);
    // monitorMessage();
    log('connect web socket channel::${uri.toString()}');
  }

  void _listenMessage(data) {
    connecting = true;
    log('receiver data: ${data.toString()}');
    var obj = jsonDecode(data);
    if (obj['event'] == 'pusher:pong') {
      SocketRequest.responsePong();
      return;
    }
    _handMessage(obj);
  }

  StreamController<ChatRoomMessageEntity> _chatMsgCtl =
      StreamController.broadcast();

  StreamController<String> _socketIdCtl = StreamController.broadcast();

  // final Stream receivedController
  void _handMessage(obj) {
    if (obj['event'] == r'App\Events\ChatMessageWasReceived') {
      final msg = getEntityFromMap<ChatRoomMessageEntity>(
          json.decode(obj['data'])['chat_room_message']);
      _chatMsgCtl.add(msg);
    } else if (obj['event'] == 'pusher:connection_established') {
      _socketIdCtl.add(json.decode(obj['data'])['socket_id']);
    }
  }

  StreamSubscription onListenerChatMessage(
      void onData(ChatRoomMessageEntity event)) {
    return _chatMsgCtl.stream.listen(onData);
  }

  StreamSubscription onListenerSocketId(void onData(String event)) {
    return _socketIdCtl.stream.listen(onData);
  }

  static sendMessage(data) {
    //发送消息
    log('send data: ${data.toString()}');
    channel.sink.add(data);
  }

  onError(error) {
    log('error: ${error.toString()}');
  }

  void onDone() async {
    if (isClose) return;
    log('connect: 断开了');
    await Future.delayed(Duration(seconds: 2));
    _init();
    await Future.delayed(Duration(milliseconds: 300));
    SocketRequest.reStartSub();
    log('connect: 正在重连');
  }

  static bool isClose = false;

  static closeWebSocket() {
    //关闭链接
    isClose = true;
    channel.sink.close();
    _singleton = null;
    log('connect: 关闭');
  }

  static void log(data) {
    // if (!_kLogData) return;
    logger.d('''\n
┌────────────────────────────────────────────────
│ Web Socket
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ $data
└────────────────────────────────────────────────''');
  }
}
